﻿using CrawlerCore.Helper;
using CrawlerCore.XmlDataTemp;
using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using System.Xml.Serialization;

namespace CrawlerCore
{
    public class AirAsia
    {
        private CrawlerHelper crawlerHelper { get; set; }
        private string address = "http://booking.airasia.com/Compact.aspx";

        private SearchInputService _input = null;
        public AirAsia()
        {
            crawlerHelper = new CrawlerHelper();
        }
        private string getPostData(SearchInputService myInput)
        {
            StringBuilder postData = new StringBuilder("");
            postData.Append("eventTarget=");
            postData.Append("&eventArgument=");
            postData.Append("&viewState=%2FwEPDwUBMGRktapVDbdzjtpmxtfJuRZPDMU9XYk%3D");
            postData.Append("&pageToken=");
            postData.Append("&culture=en-GB");
            string waytype = "RoundTrip";
            if (!myInput.IsRoundTrip)
            {
                waytype = "OneWay";
                postData.Append("&oneWayOnly=");
            }
            postData.Append("&ControlGroupCompactView%24AvailabilitySearchInputCompactView%24RadioButtonMarketStructure=" + waytype);
            postData.Append("&ControlGroupCompactView_AvailabilitySearchInputCompactVieworiginStation1=" + myInput.DepartureCode);
            postData.Append("&ControlGroupCompactView%24AvailabilitySearchInputCompactView%24TextBoxMarketOrigin1=" + myInput.DepartureCode);
            postData.Append("&ControlGroupCompactView_AvailabilitySearchInputCompactViewdestinationStation1=" + myInput.ArrivalCode);
            postData.Append("&ControlGroupCompactView%24AvailabilitySearchInputCompactView%24TextBoxMarketDestination1=" + myInput.ArrivalCode);
            postData.Append("&date_picker=" + myInput.DepartTime.Month + "%2F" + myInput.DepartTime.Day + "%2F" + myInput.DepartTime.Year);
            postData.Append("&date_picker=");
            postData.Append("&ControlGroupCompactView%24AvailabilitySearchInputCompactView%24DropDownListMarketDay1=" + myInput.DepartTime.Day);
            postData.Append("&ControlGroupCompactView%24AvailabilitySearchInputCompactView%24DropDownListMarketMonth1=" + myInput.DepartTime.ToString("yyyy-MM"));
            postData.Append("&date_picker=" + myInput.ReturnTime.Month + "%2F" + myInput.ReturnTime.Day + "%2F" + myInput.ReturnTime.Year);
            postData.Append("&date_picker=");
            postData.Append("&ControlGroupCompactView%24AvailabilitySearchInputCompactView%24DropDownListMarketDay2=" + myInput.ReturnTime.Day);
            postData.Append("&ControlGroupCompactView%24AvailabilitySearchInputCompactView%24DropDownListMarketMonth2=" + myInput.ReturnTime.ToString("yyyy-MM"));
            postData.Append("&ControlGroupCompactView%24AvailabilitySearchInputCompactView%24DropDownListPassengerType_ADT=" + myInput.Adults);
            postData.Append("&ControlGroupCompactView%24AvailabilitySearchInputCompactView%24DropDownListPassengerType_CHD=" + myInput.Children);
            postData.Append("&ControlGroupCompactView%24AvailabilitySearchInputCompactView%24DropDownListPassengerType_INFANT=" + myInput.Inf);
            postData.Append("&ControlGroupCompactView%24MultiCurrencyConversionViewCompactSearchView%24DropDownListCurrency=default");
            postData.Append("&ControlGroupCompactView%24AvailabilitySearchInputCompactView%24DropDownListSearchBy=columnView");
            postData.Append("&ControlGroupCompactView%24ButtonSubmit=Search");
            postData.Append("&__EVENTTARGET=");
            postData.Append("&__EVENTARGUMENT=");
            postData.Append("&__VIEWSTATE=%2FwEPDwUBMGRktapVDbdzjtpmxtfJuRZPDMU9XYk%3D");
            return postData.ToString();
        }
        public RootTemp CreateXmlDocument(SearchInputService input)
        {
            //CookieCollection c= crawlerHelper.getCookieCollection(adress, "POST", getPostData(input));
            _input = input;
            string posdata = getPostData(input);
            HtmlDocument d = crawlerHelper.getDocument(address, "POST", posdata, null);
            ////debug
            //File.WriteAllText("D:p.html", d.DocumentNode.InnerHtml);
            RootTemp rootxml = new RootTemp();
            rootxml.Departure = input.DepartureCode;
            rootxml.Arrival = input.ArrivalCode;
            rootxml.blocks = new List<Block>();
            rootxml.AirLine = AirLineName.airAsia;
            Block b = new Block();
            HtmlNode node = d.DocumentNode.SelectSingleNode("//div[@id='availabilityInputContent1']/div[@class='depart-section']");
            b.outBound = getOutInBound(node,true);
            node = d.DocumentNode.SelectSingleNode("//div[@id='availabilityInputContent2']/div[@class='depart-section']");
            b.inBound = getOutInBound(node,false);
            rootxml.blocks.Add(b);
            return rootxml;

        }

        private OutInBoundTemp getOutInBound(HtmlNode htmlNode,bool isOutBound)
        {
            OutInBoundTemp result = null;
            try
            {
                result = new OutInBoundTemp();
                HtmlNodeCollection nodebody = htmlNode.SelectNodes("div[1]/table/tr[@class='rgRow']");
                result.Items = getListItems(nodebody,isOutBound);
            }
            catch
            {

            }
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="htmlNodeCollection">moi the tr chua mot item</param>
        /// <returns></returns>
        private List<ItemTemp> getListItems(HtmlNodeCollection htmlNodeCollection,bool isOutBound)
        {
            List<ItemTemp> liItems = null;
            try
            {
                liItems = new List<ItemTemp>();
                int id = 0;
                foreach (HtmlNode node in htmlNodeCollection)
                {
                    try
                    {
                        ItemTemp item = new ItemTemp();
                        //lay gia
                        HtmlNode nodeTemp = node.SelectSingleNode("td[2]");
                        item.prices = getListprices(nodeTemp);
                        //lay cac segment
                        nodeTemp = node.SelectSingleNode("td[1]");
                        DateTime d=isOutBound?_input.DepartTime:_input.ReturnTime;
                        item.Segments = getListSegments(d,nodeTemp);
                        item.Id = id;
                        //item.TotalTime = node.SelectSingleNode("td[1]//ul/li[3]/strong").InnerText.Replace("Total Duration: ", "");
                        //item.TotalTime = item.TotalTime.Substring(0, item.TotalTime.IndexOf('m') + 1);
                        liItems.Add(item);
                        //chi lay 4 item
                        if (liItems.Count > 3)
                            break;
                        id++;
                    }
                    catch { }
                }
            }
            catch
            { }
            return liItems;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="htmlNode"></param>
        /// <returns></returns>
        private List<SegmentTemp> getListSegments(DateTime dateDepartReturn,HtmlNode htmlNode)
        {
            List<SegmentTemp> liS = null;
            try
            {
                liS = new List<SegmentTemp>();
                int id = 1;
                try
                {
                    HtmlNode nodeSpan = htmlNode.SelectSingleNode("div[1]/div[last()]/p/div[@class='block']/span[@class='hotspot']");
                    if (nodeSpan == null)
                        nodeSpan = htmlNode.SelectSingleNode("div[1]/div[last()]/p/div[@class='hotspot']");
                    string detailAllSegments = HttpUtility.HtmlDecode(nodeSpan.Attributes["onmouseover"].Value);
                    #region dinh dang xau
                    //bay thang
                    //                "javascript:SKYSALES.tooltip.show(\'<b>FD  642</b><br/><span style=\"font-size:10px;" +
                    //"\">Operated by Thai AirAsia</span></b><br/></b><br/>0700(DMK) - 0840(HAN)<br/>Est" +
                    //"imated flight time: 1 hours 40 minutes\',\'250\');"

                    //1 diem dung
                    //@"javascript:SKYSALES.tooltip.show('<b>FD  651</b><br/><span style=""font-size:10px;"">
                    //Operated by Thai AirAsia</span></b><br/></b><br/>0945(SGN) - 1110(DMK)<br/>
                    //Estimated flight time: 1 hours 25 minutes<br/><br/>
                    //Transit in Bangkok - Don Mueang : 2 hours 15 minutes<br/><br/>
                    //<b>FD  355</b><br/><span style=""font-size:10px;"">Operated by Thai AirAsia</span></b><br/>
                    //</b><br/>1325(DMK) - 1635(SIN)<br/>Estimated flight time: 2 hours 10 minutes','350');"
                    #endregion
                    //string pattern = @"<b>(?<FlightNo>\w{2}  \d+)</b>.+(?<DepartArrival>d{4}\(\w{3}\).{3}d{4}\(\w{3}\))"
                    //    + @".+imated flight time: (?<TotalHour>\d+) hours (?<TotalMin>\d)+ minutes.+"
                    //    + @"(Transit in (?<LayOver>\w+ - \w+) : (?<LayOverHour>\d+) hours (?<LayOverMin>\d+) minutes)*";
                    string patternFlyNo = @"<b>(?<FlightNo>\w{2}  \d+)</b>";
                    Regex regexFlyNo = new Regex(patternFlyNo);
                    string patternDepartReturn = @"(?<DepartTime>\d{4})\((?<DepartCode>\w{3})\) - (?<ArrivalTime>\d{4})\((?<ArrivalCode>\w{3})\)";
                    Regex regexDepartReturn = new Regex(patternDepartReturn);
                    string patternTotalTime = @"imated flight time: (?<TotalHour>\d+) hours (?<TotalMin>\d+) minutes";
                    Regex regexTotalTime = new Regex(patternTotalTime);
                    //Transit in Bangkok - Don Mueang : 2 hours 15 minutes
                    string patternLayOver = @"Transit in (?<LayOver>[\w\s]+ - [\w\s]+) : (?<LayOverHour>\d+) hours (?<LayOverMin>\d+) minutes";
                    Regex regexLayOver = new Regex(patternLayOver);
                    MatchCollection mcFlyNo = regexFlyNo.Matches(detailAllSegments);
                    MatchCollection mcDepartReturn = regexDepartReturn.Matches(detailAllSegments);
                    MatchCollection mcTotalTime = regexTotalTime.Matches(detailAllSegments);
                    MatchCollection mcLayOver = regexLayOver.Matches(detailAllSegments);
                    int index = 0;
                    foreach (Match m in mcFlyNo)
                    {
                        SegmentTemp s = new SegmentTemp();
                        s.flightNo = m.Groups["FlightNo"].Value;
                        s.AirLine = s.flightNo.Substring(0, 2);
                        s.duration = string.Format("{0}h{1}m", mcTotalTime[index].Groups["TotalHour"].Value, mcTotalTime[index].Groups["TotalMin"].Value);
                        if (mcLayOver != null && mcLayOver.Count > index)
                            s.layOver = string.Format("{0} - {1}h{2}m", mcLayOver[index].Groups["LayOver"].Value, mcLayOver[index].Groups["LayOverHour"].Value, mcLayOver[index].Groups["LayOverMin"].Value);
                        s.Departure = mcDepartReturn[index].Groups["DepartCode"].Value;
                        s.Arrive = mcDepartReturn[index].Groups["ArrivalCode"].Value;
                        string time=string.Format("{0}:{1}",mcDepartReturn[index].Groups["DepartTime"].Value.Substring(0,2),mcDepartReturn[index].Groups["DepartTime"].Value.Substring(2,2));
                        DateTime newDateDepartreturn = dateDepartReturn;
                        string layOver = "";
                        if (liS.Count > 0)
                        { 
                            newDateDepartreturn = liS.Last().arriveTime;
                            layOver = liS.Last().layOver.Substring(liS.Last().layOver.IndexOf('@')+1);
                        }
                        s.departureTime = DateTimeHelper.getDateAbacusDepartTime(newDateDepartreturn,time,layOver);
                        time = string.Format("{0}:{1}", mcDepartReturn[index].Groups["ArrivalTime"].Value.Substring(0, 2), mcDepartReturn[index].Groups["ArrivalTime"].Value.Substring(2, 2));
                        s.arriveTime = DateTimeHelper.getDateAbacusArriveTime(s.departureTime, time);
                        index++;
                        s.Id = id;
                        liS.Add(s);
                    }
                    id++;
                }
                catch { }
            }
            catch { }
            return liS;
        }

        private List<PriceTemp> getListprices(HtmlNode htmlNode)
        {
            List<PriceTemp> liP = null;
            try
            {
                liP = new List<PriceTemp>();
                PriceTemp p = new PriceTemp();
                p.name = "";
                //tinh tong gia cua ca nguoi lon, tre em,tre so sinh(gia da gom thue va phu phi)
                HtmlNodeCollection ncP = htmlNode.SelectNodes("div/div[@class='price']");
                int indexPrice = 0;
                if(_input.Adults>0)
                {
                    decimal price = decimal.Parse(ncP[indexPrice].InnerText.Replace(" USD", "")) * MoneyRate.MONEY_RATE;
                    p.PriceAdult = price * _input.Adults;
                    indexPrice++;
                }
                if (_input.Children > 0)
                {
                    decimal price = decimal.Parse(ncP[indexPrice].InnerText.Replace(" USD", "")) * MoneyRate.MONEY_RATE;
                    p.PriceChild = price * _input.Children;
                    indexPrice++;
                }
                if (_input.Inf > 0)
                {
                    decimal price = decimal.Parse(ncP[indexPrice].InnerText.Replace(" USD", "")) * MoneyRate.MONEY_RATE;
                    p.PriceInfant = price*_input.Inf;
                }
                liP.Add(p);
            }
            catch { }
            return liP;
        }
    }
}
